package cn.gotom.svg;

import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.RectF;
import cn.gotom.svg.xml.NumberWithUnits;
import cn.gotom.svg.xml.StyleAttribute;

public class SVGRoot extends Group
{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	NumberWithUnits x;
	NumberWithUnits y;
	NumberWithUnits width;
	NumberWithUnits height;

	RectF viewBox = null;

	public static final int PA_X_NONE = 0;
	public static final int PA_X_MIN = 1;
	public static final int PA_X_MID = 2;
	public static final int PA_X_MAX = 3;

	public static final int PA_Y_NONE = 0;
	public static final int PA_Y_MIN = 1;
	public static final int PA_Y_MID = 2;
	public static final int PA_Y_MAX = 3;

	public static final int PS_MEET = 0;
	public static final int PS_SLICE = 1;

	int parSpecifier = PS_MEET;
	int parAlignX = PA_X_MID;
	int parAlignY = PA_Y_MID;

	final Matrix viewXform = new Matrix();
	final RectF rect = new RectF();

	@Override
	public boolean updateTime(double curTime) throws SVGException
	{
		return false;
	}

	@Override
	public void render(Canvas canvas) throws SVGException
	{
		//Matrix cachedXform = canvas.getMatrix();
		//canvas.setMatrix(viewXform);
		super.render(canvas);
		//canvas.setMatrix(cachedXform);
	}

	public void build() throws SVGException
	{
		super.build();

		StyleAttribute sty = this.getAttribute("x");
		if (sty != null)
			x = sty.getNumberWithUnits();
		sty = this.getAttribute("y");
		if (sty != null)
			y = sty.getNumberWithUnits();
		sty = this.getAttribute("width");
		if (sty != null)
			width = sty.getNumberWithUnits();
		sty = this.getAttribute("height");
		if (sty != null)
			height = sty.getNumberWithUnits();
		sty = this.getAttribute("viewBox");
		if (sty != null)
		{
			float[] coords = sty.getFloatList();
			viewBox = new RectF(coords[0], coords[1], coords[2] + coords[0], coords[3] + coords[1]);
		}
		sty = this.getAttribute("preserveAspectRatio");
		if (sty != null)
		{
			String preserve = sty.getStringValue();

			if (contains(preserve, "none"))
			{
				parAlignX = PA_X_NONE;
				parAlignY = PA_Y_NONE;
			}
			else if (contains(preserve, "xMinYMin"))
			{
				parAlignX = PA_X_MIN;
				parAlignY = PA_Y_MIN;
			}
			else if (contains(preserve, "xMidYMin"))
			{
				parAlignX = PA_X_MID;
				parAlignY = PA_Y_MIN;
			}
			else if (contains(preserve, "xMaxYMin"))
			{
				parAlignX = PA_X_MAX;
				parAlignY = PA_Y_MIN;
			}
			else if (contains(preserve, "xMinYMid"))
			{
				parAlignX = PA_X_MIN;
				parAlignY = PA_Y_MID;
			}
			else if (contains(preserve, "xMidYMid"))
			{
				parAlignX = PA_X_MID;
				parAlignY = PA_Y_MID;
			}
			else if (contains(preserve, "xMaxYMid"))
			{
				parAlignX = PA_X_MAX;
				parAlignY = PA_Y_MID;
			}
			else if (contains(preserve, "xMinYMax"))
			{
				parAlignX = PA_X_MIN;
				parAlignY = PA_Y_MAX;
			}
			else if (contains(preserve, "xMidYMax"))
			{
				parAlignX = PA_X_MID;
				parAlignY = PA_Y_MAX;
			}
			else if (contains(preserve, "xMaxYMax"))
			{
				parAlignX = PA_X_MAX;
				parAlignY = PA_Y_MAX;
			}

			if (contains(preserve, "meet"))
				parSpecifier = PS_MEET;
			else if (contains(preserve, "slice"))
				parSpecifier = PS_SLICE;
		}

		prepareViewport();
	}

	private boolean contains(String text, String find)
	{
		return (text.indexOf(find) != -1);
	}

	protected void prepareViewport()
	{
		RectF deviceViewport = diagram.getDeviceViewport();
		float xx, yy, ww, hh;
		if (width != null)
		{
			xx = (x == null) ? 0 : StyleAttribute.convertUnitsToPixels(x.getUnits(), x.getValue());
			ww = StyleAttribute.convertUnitsToPixels(width.getUnits(), width.getValue());
		}
		else if (viewBox != null)
		{
			xx = (float) viewBox.left;
			ww = (float) viewBox.width();
			width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
			x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
		}
		else
		{
			// Estimate size from scene bounding box
			xx = (float) deviceViewport.top;
			ww = (float) deviceViewport.width();
			width = new NumberWithUnits(ww, NumberWithUnits.UT_PX);
			x = new NumberWithUnits(xx, NumberWithUnits.UT_PX);
		}

		if (height != null)
		{
			yy = (y == null) ? 0 : StyleAttribute.convertUnitsToPixels(y.getUnits(), y.getValue());
			if (height.getUnits() == NumberWithUnits.UT_PERCENT)
			{
				hh = height.getValue() * deviceViewport.height();
			}
			else
			{
				hh = StyleAttribute.convertUnitsToPixels(height.getUnits(), height.getValue());
			}
		}
		else if (viewBox != null)
		{
			yy = (float) viewBox.top;
			hh = (float) viewBox.bottom - viewBox.top;
			height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
			y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
		}
		else
		{
			// Estimate size from scene bounding box
			yy = (float) deviceViewport.left;
			hh = (float) deviceViewport.height();
			height = new NumberWithUnits(hh, NumberWithUnits.UT_PX);
			y = new NumberWithUnits(yy, NumberWithUnits.UT_PX);
		}
		viewXform.setTranslate(xx, yy);
		viewXform.postScale(width.getValue(), height.getValue());
		if (viewBox != null)
		{
			viewXform.postScale(1 / viewBox.width(), 1 / viewBox.height());
			viewXform.postTranslate(-viewBox.left, -viewBox.top);
		}
	}
}
